Clip Planes¶

You can use clip planes to transect the voxel-based volume rendering. This notebook is similar to the advanced clip planes notebook.

In [1]:
from pathlib import Path

from ipyniivue import download_dataset

BASE_API_URL = "https://niivue.com/demos/images/"
DATA_FOLDER = Path("images")

# Download data for example
download_dataset(
    BASE_API_URL,
    DATA_FOLDER,
    files=[
        "mni152.nii.gz",
        "hippo.nii.gz",
    ],
)
mni152.nii.gz already exists.
hippo.nii.gz already exists.
Dataset downloaded successfully to images.
In [2]:
## Setup and Imports

import ipywidgets as widgets
from IPython.display import display

from ipyniivue import NiiVue

## Initialize Viewer
nv = NiiVue()
nv.load_volumes([{"path": DATA_FOLDER / "mni152.nii.gz"}])

nv.opts.mesh_xray = 0.02
nv.set_slice_type("RENDER")
nv.set_clip_planes([[0.1, 180, 20], [0.1, 0, -20]])

## Widget Controls

cutaway_check = widgets.Checkbox(value=False, description="Cutaway")


def on_cutaway_change(change):
    """Set cutaway."""
    nv.set_cutaway(bool(change))


cutaway_check.observe(on_cutaway_change, names="value")

planes_options = ["0", "1", "2", "3", "4", "5", "6"]

planes_dropdown = widgets.Dropdown(
    options=planes_options,
    value="2",
    description="Planes:",
)


def on_planes_change(change):
    """Set clipping planes based on dropdown selection."""
    new_value = int(change["new"])
    planes = [[2.0, 180, 20]]  # default

    if new_value == 1:
        planes = [[0.1, 180, 20]]
    elif new_value == 2:
        planes = [
            [0.1, 180, 20],
            [0.1, 0, -20],
        ]
    elif new_value == 3:
        planes = [
            [0.0, 90, 0],  # right center
            [0.0, 0, -20],  # posterior oblique
            [0.1, 0, -90],  # inferior
        ]
    elif new_value == 4:
        planes = [
            [0.3, 270, 0],  # left
            [0.3, 90, 0],  # right
            [0.0, 180, 0],  # anterior
            [0.1, 0, 0],  # posterior
        ]
    elif new_value == 5:
        planes = [
            [0.4, 270, 0],  # left
            [0.4, 90, 0],  # right
            [0.4, 180, 0],  # anterior
            [0.2, 0, 0],  # posterior
            [0.1, 0, -90],  # inferior
        ]
    elif new_value == 6:
        planes = [
            [0.4, 270, 0],  # left
            [-0.1, 90, 0],  # right
            [0.4, 180, 0],  # anterior
            [0.2, 0, 0],  # posterior
            [0.1, 0, -90],  # inferior
            [0.3, 0, 90],  # superior
        ]
    else:
        planes = [[2.0, 180, 20]]  # default

    nv.set_clip_planes(planes)


planes_dropdown.observe(on_planes_change, names="value")

shade_options = ["none", "outside", "inside"]

shade_dropdown = widgets.Dropdown(
    options=shade_options,
    value="outside",
    description="Shade:",
)


def on_shade_change(change):
    """Set planes shading."""
    new_value = change["new"]
    clr = list(nv.opts.clip_plane_color)

    if new_value == "none":
        clr[3] = 0
    elif new_value == "outside":
        clr[3] = 0.5
    elif new_value == "inside":
        clr[3] = -0.5

    nv.set_clip_plane_color(clr)


shade_dropdown.observe(on_shade_change, names="value")

## Display Viewer

controls = widgets.HBox([planes_dropdown, shade_dropdown, cutaway_check])

display(controls)
display(nv)